/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package lt.ntec.danblog.server.core.model.objectify;

import com.google.inject.Inject;
import com.googlecode.objectify.*;
import java.util.*;
import lt.ntec.danblog.server.core.model.Tag;
import lt.ntec.danblog.server.core.model.TagDAO;
import lt.ntec.danblog.server.core.model.Taggable;

/**
 *
 * @author Tadas
 */
class ObjectifyTagDAO  extends ObjectifyBaseDAO<Tag> implements TagDAO  {

    static {
        ObjectifyService.register(ObjectifyTag.class);
    }
    
    @Inject
    public ObjectifyTagDAO(Objectify ofy){
        super(ofy);
    }

    @Override
    public Tag getTagByValue(String value) {
        Query<? extends Tag> q = ofy.query(getEntityClass()).
                filter("value", value);
        Tag get = q.get();
        return get;
    }

    @Override
    public HashSet<Taggable> getParentsByTag(Tag get) throws NotFoundException {
        Set<Key<Taggable>> parentKeys =
                ((ObjectifyTag) get).getParentKeys();
        HashSet<Taggable> parents = new HashSet<Taggable>();
        for (Key<Taggable> key : parentKeys) {
            parents.add(ofy.get(key));
        }
        
        return parents;
    }
    
    
    @Override
    public Tag getById(Long id) {
        Tag entity = ofy.get(new Key<Tag>(getEntityClass(), id));

        return entity;
    }

    @Override
    public void deleteParentFromTags(Taggable entity) {
        Key<Taggable> key =
                new Key<Taggable>(entity.getClass(), entity.getId());
        Query<ObjectifyTag> filter =
                ofy.query(ObjectifyTag.class).filter("parentKeys", key);
        List<ObjectifyTag> list = filter.list();
        for(ObjectifyTag tag : list){
            tag.getParentKeys().remove(key);
        }
        
        ofy.put(list);
    }

    @Override
    public SortedSet<? extends Tag> getTagsByParent(Taggable entity) {
        Key<Taggable> key =
                new Key<Taggable>(entity.getClass(), entity.getId());
        Query<ObjectifyTag> filter =
                ofy.query(ObjectifyTag.class).filter("parentKeys", key);
        List<ObjectifyTag> list = filter.list();
        return new TreeSet<Tag>(list);
    }

    @Override
    public Tag saveUniqueTag(Tag entity) {
        Tag tag = getTagByValue(entity.getValue());
        if (tag == null) {
            save(entity);
            return entity;
        }
        return tag;
    }

    @Override
    public Map<String, Set<Long>> getParentsByTagId(Long id) {
        ObjectifyTag tag = (ObjectifyTag) getById(id);
        Set<Key<Taggable>> parentKeys = tag.getParentKeys();

        Map<String, Set<Long>> map = new HashMap<String, Set<Long>>();

        for (Key<Taggable> key : parentKeys) {
            String ident = key.getKind();
            if (!map.containsKey(ident)) {
                map.put(ident,
                        new TreeSet<Long>());
            }
            map.get(ident).add(
                    key.getId());
        }
        return map;
    }
    
    
    @Override
    public Long save(Tag entity) {
        ObjectifyTag tag = (ObjectifyTag) getTagByValue(entity.getValue());
        
        ObjectifyTag real = (ObjectifyTag) entity;

        if (tag != null) {

            int parents = tag.getParentKeys().size();
            tag.setParentKeys(real.getParentKeys());
            
            if (parents != tag.getParentKeys().size()) {
                ofy.put(tag);
            }
            
            return tag.getId();
        }
        
        ofy.put(entity);
        return entity.getId();
    }

    @Override
    public Class<? extends Tag> getEntityClass() {
        return ObjectifyTag.class;
    }

}
